package com.lksoft.bz.command;

import java.util.Stack;


/**
 * History of commands
 * 
 * @author lake
 *
 */
public class History {

	// Fixed-size stack
	private Stack<Command> commandHistory = new Stack<>();
	// Redo stack
	private Stack<Command> redos = new Stack<>();
	// Max history size to be saved
	private int maxSize;
	
	// Last save
	private Command savedAt = null;
	
	/**
	 * @param maxSize Max history size to be saved 
	 * (Oldest elements will be removed from history when the size
	 * grows over this limit) 
	 */
	public History(int maxSize){
		this.maxSize = maxSize;
	}
	
	/**
	 * Add a command to the history
	 * @param command
	 */
	public void addCommand(Command command){
		// Clears the redoes
		redos.clear();
		
		commandHistory.push(command);
		if( commandHistory.size() > maxSize ){
			commandHistory.remove(0);
		}
	}
	
	/**
	 * Undoes the last registered command
	 */
	public void undo(){
		if( commandHistory.isEmpty() ) return;
		
		Command command = commandHistory.pop();
		redos.push(command);
		command.undo();
	}
	
	/**
	 * Redoes the last command that has been undone
	 */
	public void redo(){
		if( redos.isEmpty() ) return;
		
		Command command = redos.pop();
		commandHistory.push(command);
		command.redo();
	}

	/**
	 * Clear the whole history
	 */
	public void clear() {
		commandHistory.clear();
		redos.clear();
		
		savedAt = null;
	}
	
	/**
	 * @return Whether there were any changes since last save
	 */
	public boolean hasChanges(){
		if( commandHistory.isEmpty() ) return savedAt != null;
		return commandHistory.peek() != savedAt;
	}
	
	/**
	 * Notify a save completion, so that current save can be
	 * stored as "unmodified"
	 */
	public void onSave(){
		if( commandHistory.isEmpty() ){
			savedAt = null;
		} else{
			savedAt = commandHistory.peek();
		}
	}
}
